(function($) {

    /**
     * Initialize editor instances.
     *
     * This function needs to be called before the page is fully loaded, as
     * calling tinyMCE.init() after the page is loaded breaks IE6.
     *
     * @param editorSettings
     *   An object containing editor settings for each input format.
     */
    Drupal.wysiwyg.editor.init.tinymce = function(settings) {
        // If JS compression is enabled, TinyMCE is unable to autodetect its global
        // settinge, hence we need to define them manually.
        // @todo Move global library settings somewhere else.
        tinyMCE.baseURL = settings.global.editorBasePath;
        tinyMCE.srcMode = (settings.global.execMode == 'src' ? '_src' : '');
        tinyMCE.gzipMode = (settings.global.execMode == 'gzip');

        // Initialize editor configurations.
        for (var format in settings) {
            if (format == 'global') {
                continue;
            }
            tinyMCE.init(settings[format]);
            if (Drupal.settings.wysiwyg.plugins[format]) {
                // Load native external plugins.
                // Array syntax required; 'native' is a predefined token in JavaScript.
                for (var plugin in Drupal.settings.wysiwyg.plugins[format]['native']) {
                    tinyMCE.loadPlugin(plugin, Drupal.settings.wysiwyg.plugins[format]['native'][plugin]);
                }
                // Load Drupal plugins.
                for (var plugin in Drupal.settings.wysiwyg.plugins[format].drupal) {
                    Drupal.wysiwyg.editor.instance.tinymce.addPlugin(plugin, Drupal.settings.wysiwyg.plugins[format].drupal[plugin], Drupal.settings.wysiwyg.plugins.drupal[plugin]);
                }
            }
        }
    };

    /**
     * Attach this editor to a target element.
     *
     * See Drupal.wysiwyg.editor.attach.none() for a full desciption of this hook.
     */
    Drupal.wysiwyg.editor.attach.tinymce = function(context, params, settings) {
        // Configure editor settings for this input format.
        for (var setting in settings) {
            tinyMCE.settings[setting] = settings[setting];
        }

        // Remove TinyMCE's internal mceItem class, which was incorrectly added to
        // submitted content by Wysiwyg <2.1. TinyMCE only temporarily adds the class
        // for placeholder elements. If preemptively set, the class prevents (native)
        // editor plugins from gaining an active state, so we have to manually remove
        // it prior to attaching the editor. This is done on the client-side instead
        // of the server-side, as Wysiwyg has no way to figure out where content is
        // stored, and the class only affects editing.
        $field = $('#' + params.field);
        $field.val($field.val().replace(/(<.+?\s+class=['"][\w\s]*?)\bmceItem\b([\w\s]*?['"].*?>)/ig, '$1$2'));

        // Attach editor.
        tinyMCE.execCommand('mceAddControl', true, params.field);
    };

    /**
     * Detach a single or all editors.
     *
     * See Drupal.wysiwyg.editor.detach.none() for a full desciption of this hook.
     */
    Drupal.wysiwyg.editor.detach.tinymce = function(context, params) {
        if (typeof params != 'undefined') {
            tinyMCE.removeMCEControl(tinyMCE.getEditorId(params.field));
            $('#' + params.field).removeAttr('style');
        }
//  else if (tinyMCE.activeEditor) {
//    tinyMCE.triggerSave();
//    tinyMCE.activeEditor.remove();
//  }
    };

    Drupal.wysiwyg.editor.instance.tinymce = {
        addPlugin: function(plugin, settings, pluginSettings) {
            if (typeof Drupal.wysiwyg.plugins[plugin] != 'object') {
                return;
            }
            tinyMCE.addPlugin(plugin, {
                // Register an editor command for this plugin, invoked by the plugin's button.
                execCommand: function(editor_id, element, command, user_interface, value) {
                    switch (command) {
                        case plugin:
                            if (typeof Drupal.wysiwyg.plugins[plugin].invoke == 'function') {
                                var ed = tinyMCE.getInstanceById(editor_id);
                                var data = {format: 'html', node: ed.getFocusElement(), content: ed.getFocusElement()};
                                Drupal.wysiwyg.plugins[plugin].invoke(data, pluginSettings, ed.formTargetElementId);
                                return true;
                            }
                    }
                    // Pass to next handler in chain.
                    return false;
                },
                // Register the plugin button.
                getControlHTML: function(control_name) {
                    switch (control_name) {
                        case plugin:
                            return tinyMCE.getButtonHTML(control_name, settings.iconTitle, settings.icon, plugin);
                    }
                    return '';
                },
                // Load custom CSS for editor contents on startup.
                initInstance: function(ed) {
                    if (settings.css) {
                        tinyMCE.importCSS(ed.getDoc(), settings.css);
                    }
                },
                cleanup: function(type, content) {
                    switch (type) {
                        case 'insert_to_editor':
                            // Attach: Replace plain text with HTML representations.
                            if (typeof Drupal.wysiwyg.plugins[plugin].attach == 'function') {
                                content = Drupal.wysiwyg.plugins[plugin].attach(content, pluginSettings, tinyMCE.selectedInstance.editorId);
                                content = Drupal.wysiwyg.editor.instance.tinymce.prepareContent(content);
                            }
                            break;

                        case 'get_from_editor':
                            // Detach: Replace HTML representations with plain text.
                            if (typeof Drupal.wysiwyg.plugins[plugin].detach == 'function') {
                                content = Drupal.wysiwyg.plugins[plugin].detach(content, pluginSettings, tinyMCE.selectedInstance.editorId);
                            }
                            break;
                    }
                    // Pass through to next handler in chain
                    return content;
                },
                // isNode: Return whether the plugin button should be enabled for the
                // current selection.
                handleNodeChange: function(editor_id, node, undo_index, undo_levels, visual_aid, any_selection) {
                    if (node === null) {
                        return;
                    }
                    if (typeof Drupal.wysiwyg.plugins[plugin].isNode == 'function') {
                        if (Drupal.wysiwyg.plugins[plugin].isNode(node)) {
                            tinyMCE.switchClass(editor_id + '_' + plugin, 'mceButtonSelected');
                            return true;
                        }
                    }
                    tinyMCE.switchClass(editor_id + '_' + plugin, 'mceButtonNormal');
                    return true;
                },
                /**
                 * Return information about the plugin as a name/value array.
                 */
                getInfo: function() {
                    return {
                        longname: settings.title
                    };
                }
            });
        },
        openDialog: function(dialog, params) {
            var editor = tinyMCE.getInstanceById(this.field);
            tinyMCE.openWindow({
                file: dialog.url + '/' + this.field,
                width: dialog.width,
                height: dialog.height,
                inline: 1
            }, params);
        },
        closeDialog: function(dialog) {
            var editor = tinyMCE.getInstanceById(this.field);
            tinyMCEPopup.close();
        },
        prepareContent: function(content) {
            // Certain content elements need to have additional DOM properties applied
            // to prevent this editor from highlighting an internal button in addition
            // to the button of a Drupal plugin.
            var specialProperties = {
                img: {'name': 'mce_drupal'}
            };
            var $content = $('<div>' + content + '</div>'); // No .outerHTML() in jQuery :(
            jQuery.each(specialProperties, function(element, properties) {
                $content.find(element).each(function() {
                    for (var property in properties) {
                        if (property == 'class') {
                            $(this).addClass(properties[property]);
                        }
                        else {
                            $(this).attr(property, properties[property]);
                        }
                    }
                });
            });
            return $content.html();
        },
        insert: function(content) {
            content = this.prepareContent(content);
            var editor = tinyMCE.getInstanceById(this.field);
            editor.execCommand('mceInsertContent', false, content);
            editor.repaint();
        }
    };

})(jQuery);
